@node I/O system
@section I/O system

Scheme48 supports a sophisticated, non-blocking, user-extensible I/O
system untied to any particular operating system's I/O facilities.  It
is based in three levels: channels, ports, and the facilities already
built with both ports and channels in Scheme48, such as buffering.

@menu

* Ports::			Abstract & generalized I/O objects.
* Programmatic ports::		Designing custom ports.
* Miscellaneous I/O internals::	Various internal I/O system routines.
* Channels::			Low-level interface to OS facilities.
* Channel ports::		Ports built upon channels.

@end menu

@node Ports
@subsection Ports

While channels provide the low-level interface directly to the OS's I/O
facilities, @dfn{ports} provide a more abstract & generalized mechanism
for I/O transmission. Rather than being specific to channels or being
themselves primitive I/O devices, ports are functionally parameterized.
This section describes the usual I/O operations on ports.  The next
section describes the programmatic port parameterization mechanism, and
the section following that describes the most commonly used built-in
port abstraction, ports atop channels.

@subsubsection Port operations

@stindex i/o
The following names are exported by the @code{i/o} structure.

@deffn procedure input-port? value @returns{} boolean
@deffnx procedure output-port? value @returns{} boolean
These return @code{#t} if their argument is both a port and either an
input port or output port, respectively, or @code{#f} if neither
condition is true.
@end deffn

@deffn procedure close-input-port port @returns{} unspecified
@deffnx procedure close-output-port port @returns{} unspecified
Closes @var{port}, which must be an input port or an output port,
respectively.
@end deffn

@deffn procedure char-ready? [port] @returns{} boolean
@deffnx procedure output-port-ready? port @returns{} boolean
@code{Char-ready?} returns a true value if there is a character ready
to be read from @var{port} and @code{#f} if there is no character
ready.  @var{Port} defaults to the current input port if absent; see
below on current ports.  @code{Output-port-ready?} returns a true value
if @var{port} is ready to receive a single written character and
@code{#f} if not.
@end deffn

@cindex block input and output
@cindex input and output of blocks
@deffn procedure read-block block start count port [wait?] @returns{} count-read or EOF
@deffnx procedure write-block block start count port @returns{} count-written
@deffnx procedure write-string string port @returns{} char-count-written
@code{Read-block} attempts to read @var{count} elements from @var{port}
into @var{block}, which may be a string or a byte vector, starting at
@var{start}.  If fewer than @var{count} characters or bytes are
available to read from @var{port}, and @var{wait?} is a true value or
absent, @code{read-block} will wait until @var{count} characters are
available and read into @var{block}; if @var{wait?} is @code{#f},
@code{read-block} immediately returns.  @code{Read-block} returns the
number of elements read into @var{block}, or an end of file object if
the stream's end is immediately encountered.  @code{Write-block} writes
@var{count} elements from @var{block}, which may be a string or a byte
vector, starting at @var{start} to @var{port}.  @code{Write-string} is
a convenience atop @code{write-block} for writing the entirety of a
string to a port.
@end deffn

@deffn procedure newline [port] @returns{} unspecified
Writes a newline character or character sequence to the output port
@var{port}.  @var{Port} defaults to the current output port; see below
on current ports.
@end deffn

@deffn procedure disclose-port port @returns{} disclosed
Returns a disclosed representation of @var{port}; @pxref{Writer}.
@end deffn

@cindex forcing buffered output
@cindex output port buffer forcing
@cindex buffered output forcing
@cindex flushing output buffers
@deffn procedure force-output port @returns{} unspecified
Forces all buffered output in the output port @var{port} to be sent.
@end deffn

@deffn procedure make-null-output-port @returns{} output-port
Returns an output port that will ignore any output it receives.
@end deffn

@subsubsection Current ports

Scheme48 keeps in its @embedref{Fluid/dynamic bindings, dynamic
environment} a set of `current' ports.  These include R5RS's current
input and output ports, as well as ports for general noise produced by
the system, and ports for where error messages are printed.  These
procedures are exported by the @code{i/o} structure.

@deffn procedure current-input-port @returns{} input-port
@deffnx procedure current-output-port @returns{} output-port
@deffnx procedure current-noise-port @returns{} output-port
@deffnx procedure current-error-port @returns{} output-port
These return the values in the current dynamic environment of the
respective ports.  @code{Current-input-port} and
@code{current-output-port} are also exported by the @code{scheme}
structure.
@end deffn

@deffn procedure input-port-option arguments @returns{} input-port
@deffnx procedure output-port-option arguments @returns{} output-port
These are utilities for retrieving optional input and output port
arguments from rest argument lists, defaulting to the current input or
output ports.  For example, assuming the newline character sequence is
simply @code{#\newline}, @code{newline} might be written as:

@lisp
(define (newline . maybe-port)
  (write-char #\newline (output-port-option maybe-port)))@end lisp
@end deffn

@cindex noise output
@deffn procedure silently thunk @returns{} values
This stifles output from the current noise port in the dynamic extent
of @var{thunk}, which is applied to zero arguments.  @code{Silently}
returns the values that @var{thunk} returns.
@end deffn

@deffn procedure with-current-ports input output error thunk @returns{} values
@code{With-current-ports} dynamically binds the current input, output,
and error ports to @var{input}, @var{output}, and @var{error},
respectively, in the dynamic extent of @var{thunk}, which is applied
to zero arguments.  The current noise port is also bound to
@var{error}.  @code{With-current-ports} returns the values that
@var{thunk} returns.
@end deffn

@stindex i/o-internal
Similarly to @code{with-current-ports}, the @code{i/o-internal}
structure also exports these procedures:

@deffn procedure call-with-current-input-port port thunk @returns{} values
@deffnx procedure call-with-current-output-port port thunk @returns{} values
@deffnx procedure call-with-current-noise-port port thunk @returns{} values
These bind individual current ports for the dynamic extent of each
@var{thunk}, which is applied to zero arguments.  These all return the
values that @var{thunk} returns.
@end deffn

@node Programmatic ports
@subsection Programmatic ports

Ports are user-extensible; all primitive port operations on them ---
@code{read-char}, @code{write-block}, @etc{} --- are completely
generalized.  Abstractions for buffered ports are also available.

@menu

* Port data type::
* Port handlers::
* Buffered ports & handlers::

@end menu

@node Port data type
@subsubsection Port data type

@stindex ports
The @code{ports} structure defines the basis of the port data type and
exports the following procedures.

@deffn procedure make-port handler status lock data buffer index limit pending-eof? @returns{} port
Port constructor.  The arguments are all the fields of ports, which are
described below.  Note that @code{make-port} is rarely called directly;
usually one will use one of the buffered port constructors instead.
@end deffn

@deffn procedure port-handler port @returns{} port-handler
@deffnx procedure port-buffer port @returns{} buffer or @code{#f}
@deffnx procedure port-lock port @returns{} value
@deffnx procedure port-status port @returns{} integer-status
@deffnx procedure port-data port @returns{} value
@deffnx procedure port-index port @returns{} integer or @code{#f}
@deffnx procedure port-limit port @returns{} integer or @code{#f}
@deffnx procedure port-pending-eof? port @returns{} boolean
Accessors for the port fields:

@table @code
@item handler
The handler is the functional parameterization mechanism: it provides
all the port's operations, such as reading/writing blocks, disclosing
(@pxref{Writer}) the port, closing the port, @etcT{}.
@xref{Port handlers}.

@item buffer
The buffer is used for buffered ports, where it is a @embedref{Bitwise
manipulation, byte vector}.  It may be any value for unbuffered ports.

@item lock
This misnamed field was originally used for a mutual exclusion lock,
before optimistic concurrency was made the native synchronization
mechanism in Scheme48.  It is now used as a `timestamp' for buffered
ports: it is provisionally written to with a unique value when a thread
resets the @code{index} to re@"use the buffer, and it is provisionally
read from when reading from the buffer.  In this way, if the buffer is
reset while another thread is reading from it, the other thread's
proposal is invalidated by the different value in memory than what was
there when it logged the old timestamp in its proposal.

@item status
A mask from the @code{port-status-options} enumeration;
@pxref{Miscellaneous I/O internals}.
@c @xref{Architecture}.

@item data
Arbitrary data for particular kinds of ports.  For example, for a port
that tracks line & column information (@pxref{I/O extensions}), this
might be a record containing the underlying port, the line number, and
the column number.

@item index
The current index into a buffered port's buffer.  If the port is not
buffered, this is @code{#f}.

@item limit
The limit of the @code{index} field for a buffered port's buffer.  When
the @code{index} field is equal to the @code{limit} field, the buffer
is full.  If the port is not buffered, this is @code{#f}.

@item pending-eof?
For output ports, this is a boolean flag indicating whether the buffer
has been forced to output recently.  For input ports, this is a boolean
flag indicating whether an end of file is pending after reading through
the current buffer.
@end table
@end deffn

@deffn procedure set-port-lock! port value @returns{} unspecified
@deffnx procedure set-port-status! port status @returns{} unspecified
@deffnx procedure set-port-data! port data @returns{} unspecified
@deffnx procedure set-port-index! port index @returns{} unspecified
@deffnx procedure set-port-limit! port index @returns{} unspecified
@deffnx procedure set-port-pending-eof?! port pending-eof? @returns{} unspecified
These assign respective fields of ports.  The @code{buffer} and
@code{handler} fields, however, are immutable.
@end deffn

@cindex logging operations
@cindex optimistic concurrency logging operations
@deffn procedure provisional-port-handler port @returns{} port-handler
@deffnx procedure provisional-port-lock port @returns{} value
@deffnx procedure provisional-port-status port @returns{} integer-status
@deffnx procedure provisional-port-data port @returns{} value
@deffnx procedure provisional-port-index port @returns{} integer or @code{#f}
@deffnx procedure provisional-port-limit port @returns{} integer or @code{#f}
@deffnx procedure provisional-port-pending-eof? port @returns{} boolean
@deffnx procedure provisional-set-port-lock! port value @returns{} unspecified
@deffnx procedure provisional-set-port-status! port status @returns{} unspecified
@deffnx procedure provisional-set-port-data! port data @returns{} unspecified
@deffnx procedure provisional-set-port-index! port index @returns{} unspecified
@deffnx procedure provisional-set-port-limit! port index @returns{} unspecified
@deffnx procedure provisional-set-port-pending-eof?! port pending-eof? @returns{} unspecified
Provisional versions of the above port accessors & modifiers; that is,
accessors & modifiers that log in the current proposal, if there is
one.
@end deffn

@node Port handlers
@subsubsection Port handlers

@stindex i/o-internal
@dfn{Port handlers} store a port's specific operations for the general
port operations, such as block reads and writes, buffer flushing,
@etcT{}.  Port handler constructors, including @code{make-port-handler}
& the buffered port handlers in the next section, are available from
the @code{i/o-internal} structure.

@deffn procedure make-port-handler discloser closer char-reader/writer block-reader/writer readiness-tester buffer-forcer @returns{} port-handler
Basic port handler constructor.  The arguments are used for the port
handler fields.  Each field contains a procedure.  The expected
semantics of each procedure depend on whether the port is for input or
output.  Input ports do not use the @code{buffer-forcer} field.  The
first two fields are independent of the type of port:

@table @asis
@item @tabledfn{discloser, port, disclosed}
Returns a disclosed representation of the port, @ie{} a list whose
@code{car} is the `type name' of this handler (usually with a suffix of
either @code{-input-port} or @code{-output-port}) followed by a list of
all of the components to be printed; @pxref{Writer}.

@item @tabledfn{closer, port, ignored}
Closes @var{port}.  This operation corresponds with the
@code{close-input-port} & @code{close-output-port} procedures.
@end table

For input ports, the remaining fields are:

@table @asis
@item @tabledfn{char-reader, port consume?, char}
Reads a single character from @var{port}.  If @var{consume?} is true,
the character should be consumed from @var{port}; if @var{consume?} is
@code{#f}, however, the character should be left in @var{port}'s input
stream.  If @var{consume?} is true, this operation corresponds with
@code{read-char}; if it is @code{#f}, this operation corresponds with
@code{peek-char}.

@item @tabledfn{block-reader, port block start count wait?, count-written or EOF}
Attempts to read @var{count} characters from @var{port}'s input stream
into the string or byte vector @var{block}, starting at @var{start}.
In the case that an insufficient number of characters is available, if
@var{wait?} is true, the procedure should wait until all of the wanted
characters are available; otherwise, if @var{wait?} is @code{#f}, the
block reader should immediately return.  In either case, it returns the
number of characters that were read into @var{block}, or an end of file
object if it immediately reached the end of the stream.  Buffered ports
will typically just copy elements from the buffer into @var{block},
rather than reading from any internal I/O channel in @var{port}.  This
operation corresponds with @code{read-block}.

@item @tabledfn{readiness-tester, port, boolean}
Returns a true value if there is a character available to be read in
@var{port} or @code{#f} if not.  This operation corresponds with the
@code{char-ready?} procedure.
@end table

For output ports, the remaining fields are:

@table @asis
@item @tabledfn{char-writer, port char, ignored}
Writes the single character @var{char} to @var{port}.  This operation
corresponds with @code{write-char}.

@item @tabledfn{block-writer, port block start count, count-written}
Writes @var{count} characters to @var{port} from @var{block}, starting
at @var{start}.  @var{Block} may be a string or a byte vector.  This
will usually involve copying contents of @var{block} to @var{port}'s
buffer, if it is buffered.  This operation corresponds with
@code{write-block}.

@item @tabledfn{readiness-tester, port, boolean}
Returns a true value if @var{port} is ready to receive a character and
@code{#f} if not.

@item @tabledfn{buffer-forcer, port necessary?, ignored}
For buffered ports, this is intended to force all buffered output to
the actual internal I/O channel of @var{port}.  @var{Necessary?} tells
whether or not it is absolutely necessary to force all the output
immediately; if it is @code{#t}, the buffer forcer is required to force
all output in the buffer before it returns.  If @var{necessary?} is
@code{#f}, not only may it just register an I/O transaction without
waiting for it to complete, but it also should @emph{not} signal an
error if @var{port} is already closed.  For unbuffered ports, this
operation need not do anything at all.
@end table
@end deffn

@node Buffered ports & handlers
@subsubsection Buffered ports & handlers

@cindex buffered input and output
@stindex i/o-internal
Along with bare port handlers, Scheme48 provides conveniences for many
patterns of buffered ports & port handlers.  These names are exported
by the @code{i/o-internal} structure.  Buffered ports are integrated
with Scheme48's @embedref{Optimistic concurrency, optimistic
concurrency} facilities.

@strong{Note:} Although internally buffered ports are integrated with
optimistic concurrency, operations on buffered ports, like operations
on channels, cannot be reliably fusibly atomic.

@deffn procedure make-buffered-input-port handler data buffer index limit @returns{} input-port
@deffnx procedure make-buffered-output-port handler data buffer index limit @returns{} output-port
Constructors for buffered ports.  @var{Handler} is the port's handler,
which is usually constructed with one of the buffered port handler
constructors (see below).  @var{Data} is arbitrary data to go in the
port's @code{data} field.  @var{Buffer} is a byte vector whose length
is greater than or equal to both @var{index} & @var{limit}.
@var{Index} is the initial index into @var{buffer} to go in the port's
@code{index} field.  @var{Limit} is the limit in the port's buffer, to
go into the port's @code{limit} field; nothing will be written into
@var{buffer} at or past @var{limit}.
@end deffn

@deffn procedure make-unbuffered-input-port handler data @returns{} input-port
@deffnx procedure make-unbuffered-output-port handler data @returns{} output-port
Conveniences for ports that are explicitly @emph{not} buffered.  Only
the relevant fields are passed; all fields pertaining to buffering are
initialized with @code{#f}.
@end deffn

@deffn procedure make-buffered-input-port-handler discloser closer buffer-filler readiness-tester @returns{} port-handler
This creates a port handler for buffered input ports.  The arguments
are as follows:

@table @asis
@item @tabledfn{discloser, port-data, disclosed}
@itemx @tabledfn{closer, port-data, ignored}
@var{Discloser} & @var{closer} are like the similarly named regular
port handler fields, but they are applied directly to the port's data,
not to the port itself.

@item @tabledfn{buffer-filler, port wait?, committed?}
Used to fill @var{port}'s buffer when it no longer has contents from
which to read in its current buffer.  @var{Wait?} is a boolean flag,
@code{#t} if the operation should wait until the I/O transaction
necessary to fill the buffer completes, or @code{#f} if it may simply
initiate an I/O transaction but not wait until it completes (@eg{}, use
@code{channel-maybe-commit-and-read}, but not wait on the condition
variable passed to @code{channel-maybe-commit-and-read}).  
@var{Buffer-filler} is called with a fresh proposal in place, and it is
the responsibility of @var{buffer-filler} to commit it.  It returns a
boolean flag denoting whether the proposal was committed. The last call
in @var{buffer-filler} is usually either @code{(maybe-commit)} or a
call to a procedure that causes that effect (@eg{}, one of the
operation on condition variables that commits the current proposal.
@xref{Higher-level synchronization, condition variables}.)

@item @tabledfn{readiness-tester, port, [committed? ready?]}
Called when @code{char-ready?} is applied to @var{port} and the buffer
of @var{port} is empty.  Like @var{buffer-filler},
@var{readiness-tester} is applied with a fresh proposal in place, which
it should attempt to commit.  @var{Readiness-tester} should return two
values, each a boolean flag: the first denotes whether or not the
current proposal was successfully committed, and, if it was successful,
whether or not a character is ready.
@end table
@end deffn

@deffn procedure make-buffered-output-port-handler discloser buffer-emptier readiness-tester @returns{} port-handler
This creates a port handler for buffered output ports.  @var{Discloser}
& @var{closer} are as with buffered input ports.  The remaining fields
are as follows:

@table @asis
@item @tabledfn{buffer-emptier, port necessary?, committed?}
@var{Buffer-emptier} is used when @var{port}'s buffer is full and needs
to be emptied.  It is called with a fresh proposal in place.  It should
reset @var{port}'s @code{index} field, call @code{note-buffer-reuse!}
to invalidate other threads' transactions on the recycled buffer, and
attempt to commit the new proposal installed.  It returns a boolean
flag indicating whether or not the commit succeeded.

@item @tabledfn{readiness-tester, port, [committed? ready?]}
@var{Readiness-tester} is applied to @var{port} when its buffer is full
(@ie{} its @code{index} & @code{limit} fields are equal) and
@code{output-port-ready?} is applied to @var{port}.  After performing
the test, it should attempt to commit the current proposal and then
return two values: whether it succeeded in committing the current
proposal, and, if it was successful, whether or not a character is
ready to be outputted.
@end table
@end deffn

@defvr constant default-buffer-size @returns{} integer
The default size for port buffers.  This happens to be 4096 in the
current version of Scheme48.
@end defvr

@deffn procedure note-buffer-reuse! port @returns{} unspecified
@deffnx procedure check-buffer-timestamp! port @returns{} unspecified
These are used to signal the resetting of a buffer between multiple
threads.  @code{Note-buffer-reuse!} is called --- in the case of an
output port --- when a buffer fills up, is emptied, and flushed; or ---
in the case of an input port --- when a buffer is emptied and needs to
be refilled.  @code{Note-buffer-reuse!} logs in the current proposal a
fresh value to store in @var{port}.  When that proposal is committed,
this fresh value is stored in the port.  Other threads that were using
@var{port}'s buffer call @code{check-buffer-timestamp!}, which logs a
read in the current proposal.  If another thread commits a buffer
re@"use to memory, that read will be invalidated, invalidating the
whole transaction.
@end deffn

@node Miscellaneous I/O internals
@subsection Miscellaneous I/O internals

@stindex i/o-internal
@stindex architecture
All of these but @code{port-status-options} are exported by the
@code{i/o-internal} structure; the @code{port-status-options}
enumeration is exported by the @code{architecture} structure, but it
deserves mention in this section.

@defvr {enumeration} port-status-options
@lisp
(define-enumeration port-status-options
  (input
   output
   open-for-input
   open-for-output))@end lisp
Enumeration of indices into a port's @code{status} field bit set.
@end defvr

@deffn procedure open-input-port? port @returns{} boolean
@deffnx procedure open-output-port? port @returns{} boolean
These return true values if @var{port} is both an input or output port,
respectively, and open.
@end deffn

@defvr constant open-input-port-status @returns{} integer-status
@defvrx constant open-output-port-status @returns{} integer-status
The bitwise masks of enumerands from the @code{port-status-options}
enumeration signifying an open input or output port, respectively.
@end defvr

@deffn procedure make-input-port-closed! port @returns{} unspecified
@deffnx procedure make-output-port-closed! port @returns{} unspecified
These set the status of @var{port}, which must be an input or output
port, respectively, to indicate that it is closed.
@end deffn

@deffn procedure eof-object @returns{} eof-object
Returns the EOF object token.  This is the only value that will answer
true to R5RS's @code{eof-object?} predicate.
@end deffn

@deffn procedure force-output-if-open port @returns{} unspecified
This forces @var{port}'s output if it is an open output port, and does
not block.
@end deffn

@deffn procedure periodically-force-output! port @returns{} unspecified
@deffnx procedure periodically-flushed-ports @returns{} port-list
@code{Periodically-force-output!} registers @var{port} to be forced
periodically.  Only a weak reference to @var{port} in this registry is
held, however, so this cannot cause accidental space leaks.
@code{Periodically-flushed-ports} returns a list of all ports in this
registry.  Note that the returned list holds strong references to all
of its elements.  @code{Periodically-flushed-ports} does not permit
thread context switches, or interrupts of any sort, while it runs.
@end deffn

@node Channels
@subsection Channels

@cindex channels
@dfn{Channels} represent the OS's native I/O transmission channels.  On
Unix, channels are essentially boxed file descriptors, for example.
The only operations on channels are block reads & writes.  Blocks in
this sense may be either strings or @embedref{Bitwise manipulation,
byte vectors}.

@subsubsection Low-level channel operations

@stindex channels
The low-level base of the interface to channels described here is
exported from the @code{channels} structure.

@deffn procedure channel? @returns{} boolean
Disjoint type predicate for channels.
@end deffn

@deffn procedure channel-id channel @returns{} value
@deffnx procedure channel-status channel @returns{} integer-enumerand
@deffnx procedure channel-os-index channel @returns{} integer
@code{Channel-id} returns @var{channel}'s id.  The id is some
identifying characteristic of channels.  For example, file channels'
ids are usually the corresponding filenames; channels such as the
standard input, output, or error output channels have names like
@code{"standard input"} and @code{"standard output"}.
@code{Channel-status} returns the current status of @var{channel}; see
the @code{channel-status-option} enumeration below.
@code{Channel-os-index} returns the OS-specific integer index of
@var{channel}.  On Unix, for example, this is the channel's file
descriptor.
@end deffn

@cindex file channels
@deffn procedure open-channel filename option close-silently? @returns{} channel
@code{Open-channel} opens a channel for a file given its filename.
@var{Option} specifies what type of channel this is; see the
@code{channel-status-option} enumeration below.  @var{Close-silently?}
is a boolean that specifies whether a message should be printed (on
Unix, to @code{stderr}) when the resulting channel is closed after a
garbage collector finds it unreachable.
@end deffn

@cindex closing channels
@deffn procedure close-channel channel @returns{} unspecified
Closes @var{channel} after aborting any potential pending I/O
transactions it may have been involved with.
@end deffn

@deffn procedure channel-ready? channel @returns{} boolean
If @var{channel} is an input channel: returns @code{#t} if there is
input ready to be read from @var{channel} or @code{#f} if not; if
@var{channel} is an output channel: returns @code{#t} if a write would
immediately take place upon calling @code{channel-maybe-write}, @ie{}
@code{channel-maybe-write} would not return @code{#f}, or @code{#f} if
not.
@end deffn

@deffn procedure channel-maybe-read channel buffer start-index octet-count wait? @returns{} octet count read, error status cell, EOF object, or @code{#f}
@deffnx procedure channel-maybe-write channel buffer start-index octet-count @returns{} octet count written, error status cell, or @code{#f}
@deffnx procedure channel-abort channel @returns{} unspecified
@code{Channel-maybe-read} attempts to read @var{octet-count} octets
from @var{channel} into @var{buffer}, starting at @var{start-index}.
If a low-level I/O error occurs, it returns a cell containing a token
given by the operating system indicating what kind of error occurred.
If @var{wait?} is @code{#t}, and @var{channel} is not ready to be read
from, @var{channel} is registered for the VM's event polling mechanism,
and @code{channel-maybe-read} returns @code{#f}.  Otherwise, it returns
either the number of octets read, or an EOF object if @var{channel} was
was at the end.

@code{Channel-maybe-write} attempts to write @var{octet-count} octets
to @var{channel} from @var{buffer}, starting at @var{start-index}.  If
a low-level I/O error occurs, it returns a cell indicating a token
given by the operating system indicating what kind of error occurred.
If no such low-level error occurs, it registers @var{channel} for the
VM's event polling mechanism and returns @code{#f} iff zero octets were
immediately written or the number of octets immediately written if any
were.

@code{Channel-abort} aborts any pending operation registered for the
VM's event polling mechanism.
@end deffn

@deffn procedure open-channels-list @returns{} channel-list
Returns a list of all open channels in order of the @code{os-index}
field.
@end deffn

@defvr {enumeration} channel-status-option
@lisp
(define-enumeration channel-status-option
  (closed
   input
   output
   special-input
   special-output))@end lisp
Enumeration for a channel's status.  The @code{closed} enumerand is
used only after a channel has been closed.  Note that this is
@emph{not} suitable for a bit mask; that is, one may choose exactly
one of the enumerands, not use a bit mask of status options.  For
example, to open a file @file{frob} for input that one wishes the
garbage collector to be silent about on closing it:

@lisp
(open-channel "frob"
              (enum channel-status-option input)
              #t)
    @result{} #@{Input-channel "frob"@}@end lisp
@end defvr

@subsubsection Higher-level channel operations

@cindex channel utilities, higher-level
@cindex higher-level channel utilities
@stindex channel-i/o
More convenient abstractions for operating on channels, based on
@embedref{Higher-level synchronization, condition variables}, are
provided from the @code{channel-i/o} structure.  They are integrated
with Scheme48's @embedref{Optimistic concurrency, optimistic
concurrency} facilities.

@strong{Note:} Transactions on channels can @emph{not} be atomic in the
sense of optimistic concurrency.  Since they involve communication with
the outside world, they are irrevocable transactions, and thus an
invalidated proposal cannot retract the transaction on the channel.

@c What long names you have, my dear!
@deffn procedure channel-maybe-commit-and-read channel buffer start-index octet-count condvar wait? @returns{} committed?
@deffnx procedure channel-maybe-commit-and-write channel buffer start-index octet-count condvar @returns{} committed?
These attempt to commit the current proposal.  If they fail, they
immediately return @code{#f}; otherwise, they proceed, and return
@code{#t}.  If the commit succeeded, these procedures attempt an I/O
transaction, without blocking.  @code{Channel-maybe-commit-and-read}
attempts to read @var{octet-count} octets into @var{buffer}, starting
at @var{start-index}, from @var{channel}.
@code{Channel-maybe-commit-and-write} attempts to write
@var{octet-count} octets from @var{buffer}, starting at
@var{start-index}, to @var{channel}.  @var{Condvar} is noted as waiting
for the completion of the I/O transaction.  When the I/O transaction
finally completes --- in the case of a read, there are octets ready to
be read into @var{buffer} from @var{channel} or the end of the file was
struck; in the case of a write, @var{channel} is ready to receive some
octets ---, @var{condvar} is set to the result of the I/O transaction:
the number of octets read, an I/O error condition, or an EOF object,
for reads; and the number of octets written or an I/O error condition,
for writes.
@end deffn

@deffn procedure channel-maybe-commit-and-close channel closer @returns{} committed?
Attempts to commit the current proposal; if successful, this aborts any
wait on @var{channel}, sets the result of any condvars waiting on
@var{channel} to the EOF object, closes @var{channel} by applying
@var{closer} to @var{channel} (in theory, @var{closer} could be
anything; usually, however, it is @code{close-channel} from the
@code{channels} structure or some wrapper around it), and returns
@code{#t}.  If the commit failed, @code{channel-maybe-commit-and-close}
immediately returns @code{#f}.
@end deffn

@deffn procedure channel-write channel buffer start-index octet-count @returns{} octet-count-written
Atomically attempts to write @var{octet-count} octets to @var{channel}
from @var{buffer}, starting at @var{start-index} in @var{buffer}.  If
no I/O transaction immediately occurs --- what would result in
@code{channel-maybe-write} returning @code{#f} ---,
@code{channel-write} blocks until something does happen.  It returns
the number of octets written to @var{channel}.
@end deffn

@deffn procedure wait-for-channel channel condvar @returns{} unspecified
Registers @var{condvar} so that it will be set to the result of some
prior I/O transaction when some I/O event regarding @var{channel}
occurs.  (Contrary to the name, this does not actually wait or block.
One must still use @code{maybe-commit-and-wait-for-condvar} on
@var{condvar}; @pxref{Higher-level synchronization, condition
variables}.)  This is useful primarily in conjunction with calling
foreign I/O routines that register channels with the VM's event polling
system.

@strong{Note:} @code{wait-for-channel} must be called with interrupts
disabled.
@c @xref{Interrupts}.
@end deffn

@node Channel ports
@subsection Channel ports

@stindex channel-ports
Built-in to Scheme48 are ports made atop channels.  These are what are
created by R5RS's standard file operations.  The following names are
exported by the @code{channel-ports} structure.

@deffn procedure call-with-input-file filename receiver @returns{} values
@deffnx procedure call-with-output-file filename receiver @returns{} values
@deffnx procedure with-input-from-file filename thunk @returns{} values
@deffnx procedure with-output-to-file filename thunk @returns{} values
@deffnx procedure open-input-file filename @returns{} input-port
@deffnx procedure open-output-file filename @returns{} output-port
Standard R5RS file I/O operations.  (These are also exported by the
@code{scheme} structure.)  The @code{call-with-...put-file} operations
open the specified type of port and apply @var{receiver} to it; after
@var{receiver} returns normally (@ie{} nothing is done if there is a
throw out of @var{receiver}), they close the port and return the
values that @var{receiver} returned.  @code{With-input-from-file} &
@code{with-output-to-file} do similarly, but, rather than applying
@var{thunk} to the port, they dynamically bind the current input &
output ports, respectively, to the newly opened ports.
@code{Call-with-input-file}, @code{call-with-output-file},
@code{with-input-from-file}, and @code{with-output-to-file} return the
values that @var{thunk} returns.  @code{Open-input-file} &
@code{open-output-file} just open input & output ports; users of these
operations must close them manually.
@end deffn

@deffn procedure input-channel->port channel [buffer-size] @returns{} port
@deffnx procedure output-channel->port channel [buffer-size] @returns{} port
These create input & output ports atop the given channels and optional
buffer sizes.  The default buffer size is 4096 bytes.
@end deffn

@deffn procedure input-channel+closer->port channel closer [buffer-size] @returns{} port
@deffnx procedure output-channel+closer->port channel closer [buffer-size] @returns{} port
Similarly, these create input & output ports atop the given channels
and optional buffer sizes, but they allow for extra cleanup when the
resulting ports are closed.
@end deffn

@cindex port to channel conversion
@cindex accessing file ports' channels
@deffn procedure port->channel port @returns{} channel or @code{#f}
If @var{port} is a port created by the system's channel ports facility,
@code{port->channel} returns the channel it was created atop; otherwise
@code{port->channel} returns @code{#f}.
@end deffn

@deffn procedure force-channel-output-ports! @returns{} unspecified
This attempts to force as much output as possible from all of the ports
based on channels.  This is used by Scheme48's POSIX libraries before
forking the current process.
@end deffn
